<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<META content="text/html; charset=ISO-8859-2" http-equiv="content-type">
<meta name="robots" content="index,follow">
<META NAME="Keywords" CONTENT="wav, wave, wave file generaor">
<meta name="viewport" content="width=device-width, initial-scale=1">
<META NAME="Author" CONTENT="Tomasz Ostrowski">
<META name="description" content="Wave file generator">  
<link rel="stylesheet" type="text/css" media="only screen and (max-width: 959px)" href="./css/mobile.css" />
<link rel="stylesheet" type="text/css" media="only screen and (min-width: 960px)" href="./css/main.css" />
<script type="text/javascript" src="./js/tree.js"></script>


<script src="./js/jquery-2.1.3.min.js"></script>
<!-- <link rel="stylesheet" type="text/css" href="./css/jquery-eu-cookie-law-popup.css"/>
<script src="./js/jquery-eu-cookie-law-popup-en.js"></script> -->

<title>Wave file generator</title>  
</head>
<body class="eupopup eupopup-bottomleft eupopup-style-compact">

<div id="wrap">
<div id="header">
<div id="header_l">
  <a href="../index.htm">erma0.cn</a>
</div>
<div id="header_r"><A HREF="./wave_gen.htm" TARGET="_self"><strong>ENGLISH VERSION</strong></A><br><A HREF="./wave_gen.php?lang=pl" TARGET="_self"><strong>WERSJA POLSKA</strong></A></div>      
</div>

<a href="../bot-trap/">
  <img src="./images/pixel.gif" border="0" alt=" " width="1" height="1">
</a>
     

<script type="text/javascript">
//<!--
    
    function CreateFile() {
      var filename = document.frmGenerator.filename.value;
      var numberOfSamples = parseInt(document.frmGenerator.numberOfSamples.value);
      if (numberOfSamples < 0) {
        alert("Invalid number of samples!");
        return;
      }
      var samplingFrequency = parseInt(document.frmGenerator.samplingFrequency.value);
      if (samplingFrequency <= 0 || samplingFrequency > 0xFFFFFFFF) {
        alert("Invalid sampling frequency value!");
        return;
      }
      // TODO
      var bitsPerSample;
      if (document.frmGenerator.bitsPerSample.selectedIndex == 1) {
        bitsPerSample = 24;
      } else {
        bitsPerSample = 16;
      }
      var numChannels = 1;

      var binary = new Array();      
      var pos = 0;
      // "RIFF" chunk descriptor
      binary[pos++] = 'R'.charCodeAt();
      binary[pos++] = 'I'.charCodeAt();
      binary[pos++] = 'F'.charCodeAt();
      binary[pos++] = 'F'.charCodeAt();
      // skip chunksize to be filled later
      var posChunkSize = pos;
      binary[pos++] = 0x00;      
      binary[pos++] = 0x00;      
      binary[pos++] = 0x00;      
      binary[pos++] = 0x00;      
      // Format
      binary[pos++] = 'W'.charCodeAt();
      binary[pos++] = 'A'.charCodeAt();
      binary[pos++] = 'V'.charCodeAt();
      binary[pos++] = 'E'.charCodeAt();
      
      // "fmt ", subchunk 1
      binary[pos++] = 'f'.charCodeAt();
      binary[pos++] = 'm'.charCodeAt();
      binary[pos++] = 't'.charCodeAt();
      binary[pos++] = ' '.charCodeAt();
      // subchunk 1 size
      binary[pos++] = 16;
      binary[pos++] = 0;
      binary[pos++] = 0;
      binary[pos++] = 0;
      // audio format = PCM
      binary[pos++] = 1;
      binary[pos++] = 0;
      // number of channels
      binary[pos++] = numChannels & 0xFF;
      binary[pos++] = (numChannels & 0xFF00) >> 8;
      // SampleRate
      binary[pos++] = samplingFrequency & 0xFF;
      binary[pos++] = (samplingFrequency & 0xFF00) >> 8;
      binary[pos++] = (samplingFrequency & 0xFF0000) >> 16;
      binary[pos++] = (samplingFrequency & 0xFF000000) >> 24;
      // ByteRate = SampleRate * NumChannels * BitsPerSample/8
      var byteRate = samplingFrequency * numChannels * bitsPerSample/8;
      binary[pos++] = byteRate & 0xFF;
      binary[pos++] = (byteRate & 0xFF00) >> 8;
      binary[pos++] = (byteRate & 0xFF0000) >> 16;
      binary[pos++] = (byteRate & 0xFF000000) >> 24;
      // BlockAlign       == NumChannels * BitsPerSample/8
      var blockAlign = numChannels * bitsPerSample/8;
      binary[pos++] = blockAlign & 0xFF;
      binary[pos++] = (blockAlign & 0xFF00) >> 8;
      // bitsPerSample
      binary[pos++] = bitsPerSample & 0xFF;
      binary[pos++] = (bitsPerSample & 0xFF00) >> 8;
      
      // "data", subchunk 2
      binary[pos++] = 'd'.charCodeAt();
      binary[pos++] = 'a'.charCodeAt();
      binary[pos++] = 't'.charCodeAt();
      binary[pos++] = 'a'.charCodeAt();
      // Subchunk2Size    == NumSamples * NumChannels * BitsPerSample/8
      var subchunk2Size = numberOfSamples * numChannels * bitsPerSample/8;
      binary[pos++] = subchunk2Size & 0xFF;
      binary[pos++] = (subchunk2Size & 0xFF00) >> 8;
      binary[pos++] = (subchunk2Size & 0xFF0000) >> 16;
      binary[pos++] = (subchunk2Size & 0xFF000000) >> 24;
      
      var minInt;
      var maxInt;
      if (bitsPerSample == 16) {
        maxInt = -1+(1<<15);
        minInt = -1<<15;
      } else {
        maxInt = -1+(1<<23);
        minInt = -1<<23;      
      }
      
      var generateFunction = "function generateFn(){ return (" + document.frmGenerator.formula.value + ");}";
      eval(generateFunction);
            
      // actual data
      for (n = 0; n < numberOfSamples; n++) {
        var sampleValue = generateFn();
        if (sampleValue < minInt) {
          sampleValue = minInt;
        } else if (sampleValue > maxInt) {
          sampleValue = maxInt;
        }
        if (bitsPerSample == 16) {
          binary[pos++] = sampleValue & 0xFF;
          binary[pos++] = (sampleValue & 0xFF00) >> 8;
        } else {
          binary[pos++] = sampleValue & 0xFF;
          binary[pos++] = (sampleValue & 0xFF00) >> 8;
          binary[pos++] = (sampleValue & 0xFF0000) >> 16;
        }                          
      }

      // fill correct chunk size
      var chunkSizeVal = pos - 8;
      pos = posChunkSize;
      binary[pos++] = chunkSizeVal & 0xFF;
      binary[pos++] = (chunkSizeVal & 0xFF00) >> 8;
      binary[pos++] = (chunkSizeVal & 0xFF0000) >> 16;
      binary[pos++] = (chunkSizeVal & 0xFF000000) >> 24;
      
  		var byteArray = new Uint8Array(binary);
  		var a = window.document.createElement('a');
  
  		a.href = window.URL.createObjectURL(new Blob([byteArray], { type: 'application/octet-stream' }));
  		a.download = filename;
  
  		// Append anchor to body.
  		document.body.appendChild(a)
  		a.click();
  
  		// Remove anchor from body
  		document.body.removeChild(a)        
    } 

//-->
</script>


<div id="main">
<h1>Wave file generator</h1>
    <p>Client-side (javascript) wave file generator.
    <br>
    Although Audacity has some tools to generate test signals (e.g. sine wave) it lacks some features,
    in particular I could not find convenient way to use it to generate DC offset, needed to test multiple
    I2S outputs working at the same time using oscilloscope instead of real I2S codecs. This generator is intended
    to speed up this operation, previously involving generating binary file with 16-bit samples and importing it
    in Audacity as raw data.
    </p>
    <p>With this generator waveform would be described with sampling frequency (to be put in wave file header),
    number of bits per sample and javascript formula for sample values.
    <p>
    
	  <form name="frmGenerator" action="">
      <p>Sampling frequency: <input type="text" name="samplingFrequency" value="48000" style="width: 80px;"></p>
      <p>Sample size:
        <select name="bitsPerSample">
            <option value="16">16 bits</option>
            <option value="24">24 bits</option>
        </select>      
      </p>    
      <p>Number of samples in file: <input type="text" name="numberOfSamples" value="192000" style="width: 100px;"></p>

			<p>Formula (directly evaluated javascript):
        <br>
				<textarea name="formula" rows="4" cols="67" style="width: 550px;">
10000 * Math.sin(2 * Math.PI * 1000/samplingFrequency * n)
        </textarea>
        <br>
        Symbols that can be used:
        <dl class="code">
          <dt><strong>n</strong></dt>
            <dd>index of the sample</dd>
          <dt><strong>samplingFrequency</strong></dt>
            <dd>sampling frequency, (value as entered above)</dd>
        </dl>
        <br>
        Examples:
        <dl class="code">
          <dt><strong>3</strong></dt>
            <dd>fill every sample with constant value = 3</dd>
          <dt><strong>n % 10000</strong></dt>
            <dd>saw waveform with values rising from 0 to 9999 and again</dd>
          <dt><strong>( (n/(samplingFrequency/(2*50))) & 0x01 ) ? 8000 : -4000</strong></dt>
            <dd>asymmetric (+8000/-4000) 50Hz square wave</dd>
          <dt><strong>10000 * Math.sin(2 * Math.PI * 1000/samplingFrequency * n)</strong></dt>
            <dd>sine wave, 1000 Hz, amplitude = 10000</dd>
        </dl>        
        <br>
        Different waveforms can be freely combined (added).
        Sample values after calculating are saturated according to selected bit width (16 or 24 bits).       
			</p>
      
			<p>Name of file to create:</p>
	    <p>
  			<input type="text" name="filename" value="myfile.wav" style="width: 550px;">
			</p>	  
	  
		  <p>
		    <button type=button name="btnCreateFile"
           onclick="CreateFile()">
           Create file
         </button>
		  </p>
		</form>
  </div>
<div id="sidebar">
<h3>Sitemap</h3>

<ul id="tree0" class="tree">

    <li ><a>PROJECTS</a>
    <ul>
    <li><A HREF="../programator.htm" TARGET="_self">FLASH 49F programmer</A></li> 
    </ul>
    </li>

 
    <li><a>ONLINE TOOLS</a>
    <ul>
    <li><a href="./base64.htm" TARGET="_self">Base64 -&gt; HEX</A></li>
    <li><a href="./base32.htm" TARGET="_self">Base32 -&gt; HEX</a></li>
    <li><a href="./base32hex.htm" TARGET="_self">Base32hex -&gt; HEX</a></li>
    <li><a href="./ascii.htm" TARGET="_self">ASCII -&gt; HEX</a></li>
    <li><a href="./ascii_uN.htm" TARGET="_self">ASCII -&gt; u16/u32/u64 HEX</a></li>            
    <li><a href="./hex_to_base64.htm" TARGET="_self">HEX -&gt; Base64</a></li>
    <li><a href="./text_to_base64.htm" TARGET="_self">Text -&gt; Base64</a></li>
    <li><a href="./hex_to_base32.htm" TARGET="_self">HEX -&gt; Base32</a></li>
    <li><a href="./hex_to_base32hex.htm" TARGET="_self">HEX -&gt; Base32hex</a></li>
    <li><a href="./hex_to_ascii.htm" TARGET="_self">HEX -&gt; ASCII</a></li>
    <li><a href="./hex_to_dec.htm" TARGET="_self">HEX -&gt; DEC</a></li>	
    <li><a href="./dec_to_ascii.htm" TARGET="_self">DEC -&gt; ASCII</a></li>
    <li><a href="./bin_to_32bit_hex.htm" TARGET="_self">BIN &lt;-&gt; 32-bit hex</a></li>    
    <li><a href="./md5.htm" TARGET="_self">MD5 calculator</a></li>
    <li><a href="./sha1.htm" TARGET="_self">SHA1 calculator</a></li>    
    <li><a href="./regexp.htm" TARGET="_self">Regular exp.</a></li>
    <li><a href="./cpp_text_escape.htm" TARGET="_self">Text -&gt; Cpp</a></li>
    <li><a href="./cpp_unescape.htm" TARGET="_self">Cpp -&gt; text</a></li>
    <li><a href="./pascal_escape.htm" TARGET="_self">Text -&gt; Pascal</a></li>        
    <li><a href="./hex_to_file.htm" TARGET="_self">HEX -&gt; file</a></li>
    <li><a href="./file_to_hex.htm" TARGET="_self">File -&gt; HEX</a></li>
    <li><a href="./file_to_base64.htm" TARGET="_self">File -&gt; Base64</a></li>    
    <li><a href="./html_list_gen.htm" TARGET="_self">Text -&gt; HTML ul</a></li>
    <li><a href="./crc8.htm" TARGET="_self">CRC8</a></li>
    <li><a href="./wave_gen.htm" TARGET="_self">WAVE generator</a></li>
    <li><a href="./bin_decoder.htm" TARGET="_self">Bin decoder</a></li>
    <li><a href="./rc4.htm" TARGET="_self">RC4</a></li>          
    <li><a href="./xor.htm" TARGET="_self">XOR</a></li>
    <li><a href="./inv.htm" TARGET="_self">Inverting bits</a></li>
    <li><a href="./par_resistors.htm" TARGET="_self">Par. resistors search</a></li>
    <li><a href="./unique_str.htm" TARGET="_self">Deduplicate / sort</a></li>        
    <li><a href="./base64_to_PEM.htm" TARGET="_self">Base64 -&gt; PEM</a></li>
    <li><a href="./PEM_to_base64.htm" TARGET="_self">PEM -&gt; base64</a></li>
    <li><a href="./diskstats.htm" TARGET="_self">/proc/diskstats</a></li>    
    </ul>
    </li> 


    <li><A HREF="../contact2.htm" TARGET="_self">Contact</A></li></ul>
<script type="text/javascript">
//<!--
new tree("tree0");
//-->
</script>

<br>  
<br>  
<br>  





  <br>    

        
    
</div>


<div id="footer">




  
</div>


<br>
<div id="footer2"><p>      
            <!-- <font size="-2">&nbsp;"Cookie monsters": 5583818&nbsp;&nbsp;&nbsp;&nbsp;Parse time:&nbsp;0.000 s</font> -->

  </p>
	</div>
</div>
</body>
</html>

